/**
 * Copyright(c) 2008 Indrio Eko Purnomo
 * website : http://gz.indrio.name
 * email : indrio@gmail.com
 *
*/

// --gui setup--
var w;
var h;
var input_frame;

function getCurrentWindowDimension() {
     if(self.innerWidth) {
         w = self.innerWidth;
         h = self.innerHeight;
     }
     else if(document.documentElement && document.documentElement.clientWidth) {
         w = document.documentElement.clientWidth;
         h = document.documentElement.clientHeight - 20;
     }
     else if(document.body)
     {
         w = document.body.clientWidth;
         h = document.body.clientHeight;
     }
}

function setCodeAreaDimension() {
     getCurrentWindowDimension();
     //$("#code_area").width(w-300);
}

// runing for the first time
$(function(){
     getCurrentWindowDimension();
     
     editAreaLoader.init({
          id: "code"	// id of the textarea to transform		
          ,start_highlight: true	// if start with highlight
          ,allow_resize: "no"
          ,allow_toggle: false
          ,language: "en"
          ,syntax: ""	
          ,toolbar: "save, |, search, go_to_line, fullscreen, |, undo, redo, |, select_font, |, syntax_selection, |, change_smooth_selection, highlight, reset_highlight"
          ,min_height: h - 50
          ,min_width: w - 0 
          ,syntax_selection_allow: "c,cpp,css,html,java,js,perl,php,python,ruby,xml"
          ,autocomplate: true 
          ,EA_load_callback: "init"
          ,save_callback: "do_post"
          ,replace_tab_by_spaces: 5
          ,autocompletion: true
     });
     
     setCodeAreaDimension();
});


// --code change updater--
var dirty = false;
var posting = false;
var updating = false;
var old_text = ""; // must implements

// if trouble connecting to server this will be set to a negative number
// and incremented with each loop until it hits 0 and we try again.
var bad_conn_counter = 1;
var id;
var client_id;

function create_new_document() {
     try {
          $.getJSON(
          "document/createNewDocument",
          {
               
          },
          function(jsonResponse){
               if(jsonResponse.error == null) {
                    document_id = jsonResponse.id;
                    window.location='?document_id='+document_id;
               } else {
                    post_fail( jsonResponse );
               }
          });
     } catch ( err ){
          display_conn_error( "<strong> Failed to register this client </strong>" );
     }
}

function register_client( ) {
     try {
          $.getJSON(
          "connection/registerClient",
          {
          },
          function(jsonResponse){
               if(jsonResponse.error == null) {
                    client_id = jsonResponse.client_id;
               } else {
                    post_fail( jsonResponse );
               }
          });
     } catch ( err ){
          display_conn_error( "<strong> Failed to register this client </strong>" );
     }
}

function check_status() {
     if(bad_conn_counter < 0) {
          bad_conn_counter++;
          return;
     }

     if(posting) {
          return;
     }
     
     if(dirty) {
          do_post();
     } else {
          do_update();
     }
}

// do post
function do_post() {
    id = $("#document_id").val();
    var documentName = $("#documentName").val();
    var documentContent = editAreaLoader.getValue("code");
    
    if(documentContent != old_text) {
         if(documentContent.length > 200000) {
             alert("text is too long, limit of 20,000 characters\n"
             +" your text will be truncated");
             text = text.substring(0, 20000);
         }
          
         posting = true;
         old_text = documentContent;
         
         try {
              $.getJSON(
              "document/updateCurrentDocument",
              {
                   id: id,
                   documentContent:documentContent,
                   //documentName:documentName
              },
              function(jsonResponse){
                   if(jsonResponse.error == null) {
                        post_success();
                   } else {
                        post_fail( jsonResponse );
                   }
              });
         } catch ( err ){
              display_conn_error( "<strong> Failed to post to server </strong>" );
         }
    }
    dirty = false;
}

function post_success() {
    hide_conn_error();
    dirty = false;
    updating = false;
    posting = false;
}

function post_fail( json ) {
    dirty = true;
    posting = false;
    display_conn_error( "<strong>"+json.error+"</strong>" );
}

// do update
function do_update() {
    if(updating || bad_conn_counter < 0) {
        return;
    }
    
    id = $("#document_id").val();
    
    if( id != null && id.length > 0 ) {
         try {
             updating = true;
             $.getJSON(
               "connection/update",
               {
                    id: id,
                    client_id: client_id
               },
               function(jsonResponse){
                    display_conn_error( "<strong>jsonResponse.error : "+jsonResponse.error+"</strong>" );
                    if(jsonResponse.error == null) {
                         update_success( jsonResponse );
                    } else {
                         update_fail( jsonResponse );
                    }
               });
         } catch ( err ) {
               display_conn_error( "<strong> Failed to connect to server </strong>" );
         }
    }
}

function update_success( json ) {
    hide_conn_error();
    
    if(json.documentType != undefined) {
          change_lang(json.documentType);
          display_conn_error( "<strong> change lang to "+json.documentType+"</strong>" );
    }
    
    //TODO: show how many connection for this Document
    
    display_conn_error( "<strong> dirty : "+dirty+", "+(json.documentContent == undefined)+", "+!updating+"</strong>" );
    if(dirty || json.documentContent == undefined || !updating) {
        updating = false;
        return;
    }

    updating = false;
     
    var sel = editAreaLoader.getSelectionRange("code");
    var text_before = editAreaLoader.getValue("code");
    var top_before = input_frame.find("code").scrollTop;

    editAreaLoader.setValue("code", json.documentContent);

    var new_sel = get_new_highlight(sel, text_before, json.documentContent);
    editAreaLoader.setSelectionRange("the_input", new_sel.start,
        new_sel.end);

    input_frame.find("code").scrollTop = top_before;

}

function update_fail( json ) {
    updating = false;
    display_conn_error( "<strong>"+json.error+"</strong>" );
}

/*
Given the current index, text_before and new_text, return the new index.
#TODO unit test this
*/
function find_new_index(cur_idx, text_before, new_text) {
    var length = new_text.length;

    var start = cur_idx - 1;
    if(start < 0) {
        start = 0;
    }

    var end = cur_idx;
    if(end > length) {
        end = text_before.length;
    }

    while(true) {
        var tmp = text_before.substring(start, end + 1);
        var idx = new_text.indexOf(tmp);

        if(idx == -1) {
            return -1;
        }
        else if(new_text.indexOf(tmp, idx + 1) == -1) {
            return idx + cur_idx - start;
        }
        else {
            if(start == 0 && end == length) {
                return cur_idx;
            }
            if(start > 0) {
                start--;
            }
            if(end < length) {
                end++;
            }
        }
    }
}

/*
Returns a two element array with the new start and end index.
#TODO unit test this
*/
function get_new_highlight(sel, text_before, new_text) {
    if($.browser.msie) {
        new_text = new_text.replace(/\n/g, "\r\n");
    }

    var sel_text = text_before.substring(sel.start, sel.end);
    var sel_text_after = new_text.substring(sel.start, sel.end);

    // If there's no selection, reposition the cursor where it was
    if(sel_text.length == "") {
        var idx = find_new_index(sel.start, text_before, new_text);
        if(idx != -1) {
            sel.start = idx;
            sel.end = idx;
        }
        return sel;
    }

    // if the value didn't change, we're good
    if(sel_text == sel_text_after) {
        return sel;
    }
    
    //see if you can find the same string exactly once
    var idx = new_text.indexOf(sel_text);
    if(idx != -1)
    {
        // make sure there's not another instance of this string
        if(new_text.indexOf(sel_text, idx + 1) == -1)
        {
            sel.start = idx;
            sel.end = idx + sel_text.length;
            return sel;
        }
    }

    sel_text_after = new_text.substring(sel.start, sel.end);
    return sel;
}

function keypress(evt) {
    dirty = true;
}

function display_conn_error( message ) {
    //$("#status_container").css("height", "25px");
    //$("#message").css("display","inline");
    //$("#message").html(message);
    
    bad_conn_counter = -5;
}

function hide_conn_error() {
    if(bad_conn_counter == 0) {
        bad_conn_counter = 1; 
    $("#status_container").css("height", "0px");
        $("#message").css("display", "none");
    }
}

function show_state() {
    var s = "dirty: " + dirty + "\n"
        + "posting: " + posting + "\n"
        + "updating: " + updating + "\n"
        + "bad_conn_counter: " + bad_conn_counter + "\n"
        ;
    display_conn_error( s );
}

function selectDocument( document_id ) {
     try {
          $.getJSON("document/getDocumentAsJSON?id="+document_id, function(data){
               editAreaLoader.setValue("code", data.documentContent);
               
               change_lang(data.documentType);
               
               old_text = data.documentContent;
               
               $("#document_id").val(document_id);
               $("#documentName").val(data.documentName);
               
               window.title="CollabDev - "+data.documentName;
          });
     } catch ( err ) {}
}

function change_lang( lang ) {
     editAreaLoader.execCommand('code', 'change_highlight', true);
     editAreaLoader.execCommand('code', 'change_syntax', lang);
}
 
